<?php

namespace App\Models\Orders;

use App\Models\Orders\Repositories\Interfaces\OrdersInterface;
use App\Models\Orders\Repositories\Interfaces\OrderTripInfoInterface;
use App\Models\Plane\PlaneOrderFlight\PlaneOrderFlight;
use App\Models\Plane\PlaneOrderPassengers\PlaneOrderPassenger;
use App\Models\Plane\PlaneOrders\PlaneOrder;
use App\Models\Plane\PlaneOrders\Repositories\Interfaces\PlaneOrderRepositoryInterface;
use App\Models\Scenic\ScenicOrder;
use App\Models\Train\TrainOrderPassengers\TrainOrderPassenger;
use App\Models\Train\TrainOrders\Repositories\Interfaces\TrainOrdersRepositoryInterface;
use App\Models\Train\TrainOrders\TrainOrder;
use App\Models\Train\TrainOrderTrain\TrainOrderTrain;
use App\Models\Trip\TripOrderCosts\TripOrderCost;
use App\Trip\Enums\TripTypes;
use App\Trip\Orders\TripNo;
use App\Trip\Orders\TripOrderState;
use App\Trip\Orders\TripType;
use App\Trip\Traits\ModelDateTrait;
use Eloquent;
use Exception;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection;

/**
 * App\Models\Orders\Orders
 *
 * @property int                                   $id
 * @property string                                $user_id       用户id
 * @property string                                $order_sn      子单号
 * @property int                                   $transfer_flag 中转标识 0 非中转 - 1 第一程 - 2
 *           第二程
 * @property string                                $pay_sn        支付单号
 * @property string                                $trip_id       行程业务id
 * @property int                                   $order_state   订单状态 0 待支付 10 已支付 30
 *           已取消
 * @property int                                   $trip_type     订单类型 1 火车票 2 飞机票
 * @property int                                   $delete_state  删除状态 1 已删除 0 正常
 * @property string|null                           $deleted_at    删除时间
 * @property Carbon|null                           $created_at
 * @property Carbon|null                           $updated_at
 * @property string|null                           $trip_at       出行时间
 * @property int|null                              $trip_no
 * @property string|null                           $order_amount
 * @property-read TrainOrderTrain|null             $train_info
 * @property-read Collection|TrainOrderPassenger[] $train_passengers
 * @property-read int|null                         $train_passengers_count
 * @property-read Collection|TripOrderCost[]       $trip_costs
 * @property-read int|null                         $trip_costs_count
 * @method static Builder|Orders newModelQuery()
 * @method static Builder|Orders newQuery()
 * @method static Builder|Orders query()
 * @method static Builder|Orders whereCreatedAt($value)
 * @method static Builder|Orders whereDeleteState($value)
 * @method static Builder|Orders whereDeletedAt($value)
 * @method static Builder|Orders whereId($value)
 * @method static Builder|Orders whereOrderAmount($value)
 * @method static Builder|Orders whereOrderSn($value)
 * @method static Builder|Orders whereOrderState($value)
 * @method static Builder|Orders wherePaySn($value)
 * @method static Builder|Orders whereTransferFlag($value)
 * @method static Builder|Orders whereTripAt($value)
 * @method static Builder|Orders whereTripId($value)
 * @method static Builder|Orders whereTripNo($value)
 * @method static Builder|Orders whereTripType($value)
 * @method static Builder|Orders whereUpdatedAt($value)
 * @method static Builder|Orders whereUserId($value)
 * @property-read TrainOrder|null                  $train_order
 * @property int|null                              $provider_price_state 供应商价格  0 默认待确认 1 已确认
 * @property-read PlaneOrderFlight|null            $flight_info
 * @property-read PlaneOrder|null                  $plane_order
 * @property-read Collection|PlaneOrderPassenger[] $plane_passengers
 * @property-read int|null                         $plane_passengers_count
 * @method static Builder|Orders whereProviderPriceState($value)
 * @mixin Eloquent
 */
class Orders extends Model implements OrdersInterface
{
    use HasFactory, ModelDateTrait;

    protected $table = 'orders';
    protected $fillable
                     = [
            'channel_id',
            'user_id',
            'order_sn',
            'transfer_flag',
            'trip_no',
            'pay_sn',
            'trip_id',
            'order_amount',
            'order_state',
            'trip_type',
            'trip_at',
            'delete_state',
            'deleted_at',
            'created_at',
        ];

    protected $hidden = ["id", "deleted_at", "delete_state", "updated_at",];

    public function getFromNameUy(): string
    {
        return $this->getTripInfo()->getFromNameUy();
    }

    public function getTripInfo(): OrderTripInfoInterface
    {
        return $this->getRelateOrderInfo()->getTripInfo();
    }

    /**
     * @throws Exception
     */
    public function getRelateOrderInfo(): OrdersInterface
    {
        if ($this->isTrainOrder()) {
            $trainOrderRepo = app(TrainOrdersRepositoryInterface::class);
            return $trainOrderRepo->getOrderInfo($this->getOrderSn());
        } elseif ($this->isPlaneOrder()) {
            $planeOrderRepo = app(PlaneOrderRepositoryInterface::class);
            return $planeOrderRepo->getOrderInfo($this->getOrderSn());
        } else {
            throw new Exception("not support");
        }

    }

    /**
     * 是否是火车行程
     *
     * @return bool
     */
    public function isTrainOrder(): bool
    {
        return $this->getTripType() == TripType::TRIP_TYPE_TRAIN;
    }

    /**
     * 行程类型
     *
     * @return int
     */
    public function getTripType(): int
    {
        return $this->getAttribute('trip_type');
    }

    /**
     * 订单编号
     *
     * @return string
     */
    public function getOrderSn(): string
    {
        return $this->getAttribute('order_sn');
    }

    public function isPlaneOrder(): bool
    {
        return $this->getTripType() == TripType::TRIP_TYPE_PLANE;
    }

    public function getCreatedAt()
    {
        return $this->getAttribute('created_at');
    }

    public function getToNameUy(): string
    {
        return $this->getTripInfo()->getToNameUy();
    }

    /**
     * 行程序号
     *
     * @return int
     */
    public function getTripNo(): int
    {
        return $this->getAttribute('trip_no');
    }


    public function canDelete(): int
    {
        return in_array($this->getOrderState(), TripOrderState::can_delete_states()) ? 1 : 0;
    }

    /**
     * 订单状态
     *
     * @return int
     */
    public function getOrderState(): int
    {
        return $this->getAttribute('order_state');
    }

    /**
     * 是否删除了
     *
     * @return bool
     */
    public function isDelete(): bool
    {
        return $this->getAttribute('delete_state') == 1;
    }

    /**
     * OrdersRepository->lists used
     * @return HasOne
     */
    public function train_order()
    {
        return $this->hasOne(TrainOrder::class, "order_sn", "order_sn");
    }

    /**
     * OrdersRepository->lists used
     * @return HasOne
     */
    public function plane_order()
    {
        return $this->hasOne(PlaneOrder::class, "order_sn", "order_sn");
    }

    /**
     * 关联的火车订单乘客数据    OrdersRepository->lists used
     *
     * @return HasMany
     */

    public function train_passengers()
    {
        return $this->hasMany(TrainOrderPassenger::class, "order_sn", "order_sn");
    }

    /**
     * OrdersRepository->lists used
     * @return HasMany
     */
    public function plane_passengers()
    {
        return $this->hasMany(PlaneOrderPassenger::class, "order_sn", "order_sn");
    }

    /**
     * 关联的火车信息
     *OrdersRepository->lists used
     * @return HasOne
     */
    public function train_info()
    {
        return $this->hasOne(TrainOrderTrain::class, "order_sn", "order_sn");
    }

    /**
     * 关联的门票信息
     *OrdersRepository->lists used
     * @return HasOne
     */
    public function scenic_info()
    {
        return $this->hasOne(ScenicOrder::class, "order_sn", "order_sn");
    }

    public function plane_info()
    {
        return $this->flight_info();
    }

    /**
     * 关联的火车信息
     * OrdersRepository->lists used
     * @return HasOne
     */
    public function flight_info()
    {
        return $this->hasOne(PlaneOrderFlight::class, "order_sn", "order_sn");
    }


    public function getOrderAmount()
    {
        return $this->getAttribute('order_amount');
    }

    /**
     * 获取 行程(最新订单)价格明细
     *
     * @return array
     */
    public function getPriceDetails(): array
    {
        // 获取当前行程最新的订单
        $currentOrders = $this->where('trip_id', $this->getTripId())
                              ->where('user_id', $this->getUserId())
                              ->get();

        $order_sns            = collect($currentOrders)->pluck('order_sn')->toArray();
        $costs                = $this->trip_costs()->get()
                                     ->whereIn('order_sn', $order_sns)
                                     ->toArray();
        $trips_fees           = [];
        $trip_desc            = TripNo::TRIP_NO_DESC;
        $total_price          = 0;
        $waiting_confirm      = false;
        $waiting_confirm_desc = __('待确认');
        foreach ($costs as $cost) {
            $price = $cost['price'];
            if ($price < 0) {
                $waiting_confirm = true;
            }
            $trip_no     = $cost['trip_no'];
            $cost_total  = $waiting_confirm ? 0 : $price * $cost['count'];
            $total_price += $cost_total;
            if (!isset($trips_fees[$cost['trip_no']])) {
                $trips_fees[$cost['trip_no']]
                    = [
                    "name"            => $trip_desc[$trip_no] ?? '',
                    "name_uy"         => trans2uy($trip_desc[$trip_no] ?? ''),
                    "total_price"     => $waiting_confirm ? $waiting_confirm_desc : $cost_total,
                    "waiting_confirm" => $waiting_confirm,
                    "details"         => [
                        [
                            "type"          => $cost["type"],
                            "name"          => $cost["name"],
                            "detail"        => $cost["detail"] ?? "",
                            "name_uy"       => trans2uy($cost["name"]),
                            "price"         => $cost["price"],
                            "count"         => $cost["count"],
                            "confirm_state" => $cost["confirm_state"],
                        ],
                    ],
                ];
            } else {
                if ($trips_fees[$cost['trip_no']]["waiting_confirm"] || $waiting_confirm) {
                    $trips_fees[$cost['trip_no']]["total_price"] = $waiting_confirm_desc;
                } else {
                    $trips_fees[$cost['trip_no']]["total_price"]     += $cost_total;
                    $trips_fees[$cost['trip_no']]["waiting_confirm"] += $waiting_confirm;
                }

                $trips_fees[$cost['trip_no']]["details"][] = [
                    "type"          => $cost["type"],
                    "name"          => $cost["name"],
                    "detail"        => $cost["detail"] ?? "",
                    "name_uy"       => trans2uy($cost["name"]),
                    "price"         => $cost["price"],
                    "count"         => $cost["count"],
                    "confirm_state" => $cost["confirm_state"],
                ];
            }
        }
        if ($waiting_confirm) {
            $total_price = $waiting_confirm_desc;
        }
        return [
            'total_price' => $total_price,
            'trips'       => array_values($trips_fees),
        ];
    }

    /**
     * 行程id
     *
     * @return string
     */
    public function getTripId(): string
    {
        return $this->getAttribute('trip_id');
    }

    /**
     * 用户id
     *
     * @return string
     */
    public function getUserId(): string
    {
        return $this->getAttribute('user_id');
    }

    /**
     * 订单-行程 关联的消费明细记录
     *
     * @return HasMany
     */
    public function trip_costs()
    {
        return $this->hasMany(TripOrderCost::class, 'trip_id', 'trip_id');
    }

    /**
     * @throws Exception
     */
    public function getPassengers(): Collection
    {
        return $this->getRelateOrderInfo()->getPassengers();
    }

    /**
     * @throws Exception
     */
    public function getTripDate(): string
    {
        return $this->getRelateOrderInfo()->getTripDate();
    }

    public function getChannelId(): int
    {
        return $this->channel_id;
    }

    public function tripType(): TripTypes
    {
        return TripTypes::from($this->getTripType());
    }
}
